﻿using Newtonsoft.Json;
using System.Net;
using static System.Net.Mime.MediaTypeNames;

namespace OConf.NetCore.Common
{
    public static class HttpRequestUnit
    {
        private static IHttpClientFactory _httpClientFactory;
        public static void InitHttpUnit(IHttpClientFactory httpClientFactory)
        {
            if (httpClientFactory == null)
            {
                throw new ArgumentNullException("IHttpClientFactory not is null");
            }

            _httpClientFactory = httpClientFactory;
        }

        private static Dictionary<string, string> globalHeaders = new Dictionary<string, string>();

        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requestParam"></param>
        /// <param name="headers"></param>
        /// <param name="timeout">超时时间/秒</param>
        /// <returns></returns>
        /// <exception cref="HttpException"></exception>
        public static async Task<string> GetAsync(string url, SortedDictionary<string, string>? requestParam = null, Dictionary<string, string>? headers = null, int? timeout = 120)
        {
            if (requestParam != null)
            {
                string param = "?";
                foreach (var item in requestParam)
                {
                    param += $"{item.Key}={item.Value}&";
                }
                param = param.TrimEnd('&');
                url += param;
            }

            var httpClient = _httpClientFactory?.CreateClient() ?? new HttpClient();

            if (timeout.HasValue)
            {
                httpClient.Timeout = TimeSpan.FromSeconds(timeout.Value);
            }

            httpClient = httpClient.AttachHeader(globalHeaders);

            if (headers != null)
            {
                httpClient = httpClient.AttachHeader(headers);
            }

            var httpResponseMessage = await httpClient.GetAsync(url);

            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return await httpResponseMessage.Content.ReadAsStringAsync();
            }
            throw new HttpException(httpResponseMessage.StatusCode, httpResponseMessage?.ReasonPhrase ?? "");
        }

        /// <summary>
        /// Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requestParam"></param>
        /// <param name="headers"></param>
        /// <param name="timeout">超时时间/秒</param>
        /// <returns></returns>
        /// <exception cref="HttpException"></exception>
        public static async Task<string> PostAsync(string url, SortedDictionary<string, object>? requestParam = null, Dictionary<string, string>? headers = null, int? timeout = 120)
        {
            var httpClient = _httpClientFactory?.CreateClient() ?? new HttpClient();
            httpClient = httpClient.AttachHeader(globalHeaders);

            if (timeout.HasValue)
            {
                httpClient.Timeout = TimeSpan.FromSeconds(timeout.Value);
            }

            if (headers != null)
            {
                httpClient = httpClient.AttachHeader(headers);
            }

            StringContent jsonItem = requestParam == null ? null : new StringContent(JsonConvert.SerializeObject(requestParam), System.Text.Encoding.UTF8, Application.Json);

            var httpResponseMessage = await httpClient.PostAsync(url, jsonItem);
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return await httpResponseMessage.Content.ReadAsStringAsync();
            }
            throw new HttpException(httpResponseMessage.StatusCode, httpResponseMessage?.ReasonPhrase ?? "");
        }
    }

    public static class HttpRequestUnitExtensions
    {
        /// <summary>
        /// 添加请求头部
        /// </summary>
        /// <param name="httpClient"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static HttpClient AttachHeader(this HttpClient httpClient, Dictionary<string, string> headers)
        {
            if (httpClient == null)
            {
                throw new Exception("HttpClient is null");
            }

            foreach (var item in headers)
            {
                httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
            }

            return httpClient;
        }
    }

    public class HttpException : Exception
    {
        /// <summary>
        /// 错误码
        /// </summary>
        public HttpStatusCode StatusCode { get; set; }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMsg { get; set; } = "";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="statusCode">错误码</param>
        /// <param name="errorMsg">ErrorMsg</param>
        public HttpException(HttpStatusCode statusCode, string errorMsg) : base()
        {
            StatusCode = statusCode;
            ErrorMsg = errorMsg;
        }
    }
}
